<?php

declare(strict_types=1);

namespace App\Http\Common\Middleware;

use Common\Common;
use Psr\Http\Server\MiddlewareInterface;
use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Server\RequestHandlerInterface;
use Psr\Http\Message\ResponseInterface;

final class ApiInfoMiddleware implements MiddlewareInterface
{
    public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface
    {
        if (env('APP_ENV') !== 'dev' || env('APP_DEBUG') !== true) {
            return $handler->handle($request);
        }
        $method = $request->getMethod();
        $path = $request->getUri()->getPath();
        $source =  json_encode($request->getServerParams(), JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE);
        if ($method == 'POST' || $method == 'PUT' || $method == 'DELETE') {
            $params = json_encode($request->getParsedBody(), JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE);
        } else {
            $params = json_encode($request->getBody(), JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE);
        }
        $requestMessage = <<<message
            ------------------REQUEST MESSAGE---------------
            METHOD:{$method}
            PATH:{$path}
            PARAMS:{$params}
            REMOTE:{$source}
            ------------------------------------------------\n
            message;
        echo $requestMessage;
        Common::log(__CLASS__, "request method:{$method}, path:{$path} \nparams:{$params}, remote:{$source}");
        $startTime = microtime(true);
        $result =  $handler->handle($request);
        // 以毫秒为单位计算执行时间
        $endTime = microtime(true);
        $executionTime = ($endTime - $startTime) * 1000;
        $message = <<<message
        ------------------RESPONSE MESSAGE-------------------
        PATH:{$path}
        TIME:{$executionTime} ms
        ------------------------------------------------\n
        message;
        echo $message;
        // 判断响应内容类型，文件内容不打印
        $contentType = $result->getHeaderLine('Content-Type');
        $isFileContent = preg_match('/^(application\/octet-stream|application\/pdf|application\/zip|image\/|audio\/|video\/)/i', $contentType);
        if (!$isFileContent) {
            Common::log(__CLASS__, "response time:{$executionTime} ms \nresponse:{" . $result->getBody()->getContents() . '}', 'info');
        } else {
            Common::log(__CLASS__, "response time:{$executionTime} ms \nresponse:{[file content omitted]}", 'info');
        }
        return $result;
    }
}
